<template>
  <div class="designer-container">
    <el-container v-if="mounted">
      <el-header style="padding: 0">
        <el-menu
          default-active="BASE"
          class="designer-container-menu"
          mode="horizontal"
          @select="switchMenu"
        >
          <div>
            <el-button v-if="fullscreen" icon="arrow-left" circle @click="handleClose"> </el-button>
            <IconifyIconOnline
              :icon="processDef.icon.name"
              class="w-process-icon"
              :style="{
                background: processDef.icon.bgc,
                color: processDef.icon.color
              }"
            />
            <el-text>{{ processDef.flowName }}</el-text>
          </div>
          <el-menu-item index="BASE">①基础设置</el-menu-item>
          <el-menu-item index="PROCESS">②流程设计</el-menu-item>
          <div>
            <el-button v-if="fullscreen" icon="Close" type="warning" round @click="handleClose"
              >关闭</el-button
            >
            <el-button icon="FolderChecked" round @click="handleSave">保存</el-button>
            <el-button icon="Promotion" type="primary" round @click="handlePublish">发布</el-button>
          </div>
        </el-menu>
      </el-header>
      <el-main
        :class="{
          'designer-container-content': true,
          'designer-container-content-fullscreen': fullscreen
        }"
      >
        <ProcessBaseSetting v-show="active === 'BASE'" ref="base" v-model:defFlow="processDef" />
        <ProcessDesigner
          v-show="activePd"
          ref="process"
          v-model="flowDef"
          v-model:defFlow="processDef"
          :active="activePd"
          :fullscreen="props.fullscreen"
        />
      </el-main>
    </el-container>
    <DesignerValidate
      ref="processValidateRef"
      v-model:validRefs="validRefs"
      :instance="_this"
      @success="handleValidSuccess"
    />
  </div>
</template>
<script setup name="FlowDesign" lang="ts">
import { computed, ref, getCurrentInstance, onMounted, watchEffect } from "vue";
import ProcessDesigner from "./ProcessDesigner.vue";
import ProcessBaseSetting from "../ProcessBaseSetting.vue";
import DesignerValidate from "../DesignerValidate.vue";
import { addOrUpdateObj } from "@/api/flow/def/";
import { useMessage } from "@/hooks/message";
import { cloneObject } from "@/utils/common";
import { type DefFlowModel, type FlowModelNode } from "./ProcessDef";

const _this = getCurrentInstance();
const active = ref("BASE");
const processValidateRef = ref(null);
const processDefModel = defineModel<DefFlowModel>("processDef");
const mounted = ref(false);
const flowDef: any = ref<FlowModelNode[]>([]);
const processDef = ref<DefFlowModel>({
  id: "",
  flowName: "未命名流程",
  flowKey: "",
  icon: {
    name: "file-icons:omnigraffle",
    bgc: "#4C87F3",
    color: "#FFFFFF"
  },
  formId: "",
  formName: "",
  status: "-1",
  version: 1,
  sort: 1,
  groupId: "1",
  remark: null,
  flowDef: ""
});

const props = defineProps({
  fullscreen: {
    type: Boolean,
    default: false
  }
});

const emits = defineEmits(["closed"]);

const activePd = computed(() => {
  return active.value === "PROCESS";
});

const validRefs = ref([
  { _ref: "base", name: "基础设置", status: "" },
  { _ref: "process", name: "流程设计", status: "" }
]);

onMounted(() => {
  mounted.value = true;
});

watchEffect(() => {
  if (processDefModel.value) {
    processDef.value = processDefModel.value;
    if (processDefModel.value.flowDefJson) {
      flowDef.value = processDefModel.value.flowDefJson;
    } else {
      flowDef.value = [];
    }
  }
});

function switchMenu(index) {
  if (active.value === "BASE") {
    const compRef = _this.refs[validRefs.value[0]._ref];
    compRef
      ?.validate()
      .then(() => {
        active.value = index;
      })
      .catch(() => {
        active.value = "BASE";
        return false;
      });
  } else {
    active.value = index;
  }
}

function handleSave() {
  processDef.value.status = "-1";
  processValidateRef.value
    .validate(processDef.value.status)
    .then(() => {
      processValidateRef.value.reloadValidResult(true);
    })
    .catch(errs => {
      processValidateRef.value.reloadValidResult(false);
      const validIndex = processValidateRef.value.getValidIndex();
      validRefs.value[validIndex].status = "error";
      if (Array.isArray(errs)) {
        processValidateRef.value.addValidResult(errs);
      }
    });
}

function handlePublish() {
  processDef.value.status = "1";
  processValidateRef.value
    .validate(processDef.value.status)
    .then(() => {
      processValidateRef.value.reloadValidResult(true);
    })
    .catch(errs => {
      processValidateRef.value.reloadValidResult(false);
      const validIndex = processValidateRef.value.getValidIndex();
      validRefs.value[validIndex].status = "error";
      if (Array.isArray(errs)) {
        processValidateRef.value.addValidResult(errs);
      }
    });
}

const saveOrPublish = () => {
  const params = {
    def: processDef.value,
    flowDef: JSON.stringify(flowDef.value)
  };
  addOrUpdateObj(params)
    .then(res => {
      if (res.code === 200) {
        cloneObject(processDef.value, res.data);
        useMessage().success("保存成功");
      } else {
        useMessage().error(res.msg);
      }
    })
    .catch(() => {
      useMessage().error("保存失败");
    });
};

const handleValidSuccess = () => {
  saveOrPublish();
};

const handleClose = () => {
  emits("closed");
};
</script>
<style lang="scss" scoped>
.designer-container {
  background: $main-bgc;

  .designer-container-menu {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    background: white;

    & > div:first-child {
      position: absolute;
      left: 20px;
      display: flex;
      align-items: center;

      .w-process-icon {
        margin: 0 10px 0 20px;
      }
    }

    & > div:last-child {
      position: absolute;
      right: 20px;
    }
  }

  .designer-container-content {
    height: 565px;
    padding: 5px !important;
    overflow: hidden;
  }

  .designer-container-content-fullscreen {
    height: calc(100vh - 70px) !important;
    padding: 5px !important;
    overflow: hidden;
  }

  .w-no-padding {
    padding: 0;
  }
}
</style>
